package com.moon.game.proxy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.moon.game.constants.GlobalConstants;
import com.moon.game.exception.GException;
import com.moon.game.message.ObjMessage;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;

/**
 * @author Ranger 作者 E-mail:haozi000005@163.com
 * @version 创建时间：2012-4-21 上午9:12:05
 * @description 
 */
public class ProxyUtil {
	private static Configuration freemakaer;
	private static final Logger log = Logger.getLogger(ProxyUtil.class);
	public static Map<String, Map<String, String>> templates = new HashMap<String, Map<String,String>>();
	
	/**
	 * 初始化freemaker
	 * @throws GException 
	 */
	public static void initFreemaker() throws GException {
		if (freemakaer == null) {
			freemakaer = new Configuration();
			try {
				freemakaer.setDirectoryForTemplateLoading(new File("templates"));
			} catch (IOException e) {
				throw new GException(e.getMessage());
			}
		}
		BeansWrapper wrapper = (BeansWrapper) BeansWrapper.BEANS_WRAPPER;
		wrapper.setExposureLevel(BeansWrapper.EXPOSE_ALL);
		try {
			TemplateHashModel staticModels = wrapper.getStaticModels();
			TemplateHashModel MD5Static = (TemplateHashModel) staticModels.get("com.moon.game.util.MD5");
			freemakaer.setSharedVariable("MD5", MD5Static);
			TemplateHashModel monster = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.Monster");
			freemakaer.setSharedVariable("monster", monster);
			TemplateHashModel fightResult = (TemplateHashModel) staticModels.get("com.moon.game.vos.FightResult");
			freemakaer.setSharedVariable("fightResult", fightResult);
			TemplateHashModel player = (TemplateHashModel) staticModels.get("com.moon.game.vos.PlayerVo");
			freemakaer.setSharedVariable("player", player);
			TemplateHashModel item = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.Item");
			freemakaer.setSharedVariable("item", item);
			TemplateHashModel playerItemVo = (TemplateHashModel) staticModels.get("com.moon.game.vos.PlayerItemVo");
			freemakaer.setSharedVariable("playerItemVo", playerItemVo);
			TemplateHashModel errMsg = (TemplateHashModel) staticModels.get("com.moon.game.vos.ErrorMsg");
			freemakaer.setSharedVariable("errMsg", errMsg);
			TemplateHashModel npc = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.Npcs");
			freemakaer.setSharedVariable("npc", npc);
			TemplateHashModel msg = (TemplateHashModel) staticModels.get("com.moon.game.vos.MsgVo");
			freemakaer.setSharedVariable("msg", msg);
			TemplateHashModel dateUtil = (TemplateHashModel) staticModels.get("com.moon.game.util.GDateUtils");
			freemakaer.setSharedVariable("dateUtil", dateUtil);
			TemplateHashModel mainland = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.MainLand");
			freemakaer.setSharedVariable("mainland", mainland);
			TemplateHashModel proxyConstants = (TemplateHashModel) staticModels.get("com.moon.game.constants.Constants");
			freemakaer.setSharedVariable("constants", proxyConstants);
			TemplateHashModel gameDateUtil = (TemplateHashModel) staticModels.get("com.moon.game.util.GDateUtils");
			freemakaer.setSharedVariable("gameDateUtil", gameDateUtil);
			TemplateHashModel tower = (TemplateHashModel) staticModels.get("com.moon.game.vos.PlayerVo$Tower");
			freemakaer.setSharedVariable("tower", tower);
			TemplateHashModel pet = (TemplateHashModel) staticModels.get("com.moon.game.vos.PlayerVo$Pet");
			freemakaer.setSharedVariable("pet", pet);
			TemplateHashModel rentingBean = (TemplateHashModel) staticModels.get("com.moon.game.vos.RentLairBean");
			freemakaer.setSharedVariable("rentingBean", rentingBean);
			TemplateHashModel animal = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.Animal");
			freemakaer.setSharedVariable("animal", animal);
			TemplateHashModel notice = (TemplateHashModel) staticModels.get("com.moon.game.resource.model.Notice");
			freemakaer.setSharedVariable("notice", notice);
			TemplateHashModel errCode = (TemplateHashModel) staticModels.get("com.moon.game.constants.ErrorCode");
			freemakaer.setSharedVariable("errCode", errCode);
			TemplateHashModel resource = (TemplateHashModel) staticModels.get("com.moon.game.resources.DBResource");
			freemakaer.setSharedVariable("resource", resource);
			TemplateHashModel gift = (TemplateHashModel) staticModels.get("com.moon.game.vos.GiftVo");
			freemakaer.setSharedVariable("gift", gift);
			freemakaer.setSharedVariable("statics", BeansWrapper.getDefaultInstance().getStaticModels());
		} catch (Exception ex) {
			log.error("exception", ex);
			throw new GException(ex);
		}
	}
	/**
	 * 加载模版
	 * 
	 * @param file
	 */
	public static void loadTemplates(String file) {
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(file));
			String line = null;
			int sum = 0;
			while ((line=br.readLine()) != null) {
				if (StringUtils.isBlank(line)) {
					continue;
				}
				// 注释
                if (line.startsWith("#")) {
                    continue;
                }
                // 规则内容
                if (StringUtils.isNotBlank(line)) {
					String[] conf = line.split("[;]");
					String cmd = conf[0].trim();
					String statu = conf[1].trim();
					String template = conf[2].trim();
					Map<String, String> cell = new HashMap<String, String>();
					cell.put(statu, template);
					sum++;
					if (templates != null && templates.get(cmd)!=null) {
						Map<String, String> temp = templates.get(cmd);
						cell.putAll(temp);
					}
					templates.put(cmd, cell);
					
				}
			}
			if (templates.size() > 0) {
				log.debug("templates init num:[" + sum +"]");
			}
		} catch (FileNotFoundException e) {
			log.error(e.getMessage(),e);
		} catch (IOException e) {
			log.error(e.getMessage(),e);
		}
	}
	
	/**
	 * 获取模板文件.
	 * 
	 * @param result
	 * @throws GException 
	 */
	public static Template getTemplate(ObjMessage result) throws GException {
		String cmd = result.getCmd();
		String statu = result.getStatus();
		Map<String, String> cell = templates.get(cmd);
		if (cell == null) {
			throw new GException("get cell fail,null:" + cmd);
		}
		log.debug("match-cmd:" + result.getCmd() + ",status:" + result.getStatus() + ",file:" + cell.get(statu));
		try {
			return freemakaer.getTemplate(cell.get(statu), GlobalConstants.UTF_8);
		} catch (IOException e) {
			e.printStackTrace();
			throw new GException("get template fail:" + cmd);
		}
	}
	
	/**
	 * 获得模版路径
	 * 
	 * @param result
	 * @return
	 * @throws GException
	 */
	public static String getTemplateDir(ObjMessage result) throws GException {
		String cmd = result.getCmd();
		String statu = result.getStatus();
		Map<String, String> cell = templates.get(cmd);
		if (cell == null) {
			throw new GException("get cell fail,null:" + cmd);
		}
		log.debug("match-cmd:" + result.getCmd() + ",status:" + result.getStatus() + ",file:" + cell.get(statu));
		return cell.get(statu);
	}
	
	/**
	 * 解析FTL生成字符串.
	 * 
	 * @param result
	 *            template data
	 * @return template result
	 * @throws Exception
	 *             parse exception
	 */
	public static String parseFtl(ObjMessage result) throws GException {
		Template template = getTemplate(result);
		if (template == null) {
			throw new GException("template is not exists! cmd:" + result.getCmd() + ",status:" + result.getStatus());
		}
		template.setEncoding(GlobalConstants.UTF_8);
		StringWriter out = new StringWriter();
		try {
			template.process(result.getData(), out);
		} catch (TemplateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return out.toString();
	}
}
